package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DateTimeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.CustomRecheckRulePojo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.RecheckingAddRuleHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.ClueRecheckFormPojo;
import com.xbongbong.paas.pojo.RecheckJointLinkAttrPojo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.recheck.pojo.RecheckAttrRulePojo;
import com.xbongbong.pro.recheck.pojo.RecheckFormRulePojo;
import com.xbongbong.pro.recheck.pojo.dto.RecheckingRuleGetDTO;
import com.xbongbong.pro.recheck.pojo.dto.RecheckingRuleSaveDTO;
import com.xbongbong.pro.recheck.pojo.vo.RecheckingAttrListVO;
import com.xbongbong.pro.recheck.pojo.vo.RecheckingFieldListVO;
import com.xbongbong.pro.recheck.pojo.vo.RecheckingRuleListVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.RecheckingRuleEntity;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RecheckMatchWayEnum;
import com.xbongbong.saas.enums.RepeatTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.RecheckingRuleHelp;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.RecheckingRuleModel;
import com.xbongbong.saas.service.RecheckingRuleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * @description 重复规则业务逻辑层
 * @author yanglei
 * @date 2022/11/8 19:08
 */
@Service("recheckingRuleService")
@Slf4j
public class RecheckingRuleServiceImpl implements RecheckingRuleService {

    @Resource
    private RecheckingRuleModel recheckingRuleModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private RecheckingRuleHelp recheckingRuleHelp;
    @Resource
    private RecheckingAddRuleHelp recheckingAddRuleHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;

    /**
     * @description 重复规则支持选择的字段类型
     * @author yanglei
     * @date 2022/11/10 11:14
     * @return List<Integer>
     */
    public static List<Integer> getRecheckingAttrType(){
        return Arrays.asList(FieldTypeEnum.USER.getType(),FieldTypeEnum.TEXT.getType(), FieldTypeEnum.SUB_FORM.getType(), FieldTypeEnum.CONTACT_NUMBER.getType(),FieldTypeEnum.SERIALNO.getType());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer save(RecheckingRuleSaveDTO saveDTO) throws XbbException {
        String corpid = saveDTO.getCorpid();
        Long formId = saveDTO.getFormId();
        Integer businessType = saveDTO.getBusinessType();
        PaasFormEntityExt paasForm = paasFormModel.getByKey(formId, corpid);
        //查重工具规则
        List<RecheckFormRulePojo> checkToolRule = saveDTO.getCheckToolRule();
        //新建不允许重复规则
        List<RecheckFormRulePojo> noRepeatRule = saveDTO.getNoRepeatRule();
        if (Objects.isNull(paasForm)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
        }
        //校验查重工具规则
        //verifyAttrRepeat(businessType,checkToolRule);
        //校验新建不允许重复规则
        //verifyAttrRepeat(businessType,noRepeatRule);
        Integer result;
        Long oldUpdateTimeLong;
        Integer oldNormalEnable;
        try {
            //获取当前表单的重复规则
            RecheckingRuleEntity ruleEntity = recheckingRuleModel.getRuleListByFormId(corpid, formId, businessType);
            oldUpdateTimeLong = ruleEntity.getUpdateTime();
            oldNormalEnable = ruleEntity.getNormalEnable();
            boolean isNew = Objects.equals(ruleEntity.getCorpid(), StringConstant.DEFAULT_CORPID);
            String noRepeatRuleStr = JSON.toJSONString(saveDTO.getNoRepeatRule());
            String checkToolRuleStr = JSON.toJSONString(saveDTO.getCheckToolRule());
            if (isNew){
                //默认规则，证明该公司的规则是从0 - 1 ，新增实体
                RecheckingRuleEntity newEntity = new RecheckingRuleEntity();
                BeanUtil.copyProperties(saveDTO,newEntity);
                newEntity.setNoRepeatRule(noRepeatRuleStr);
                newEntity.setCheckToolRule(checkToolRuleStr);
                result = recheckingRuleModel.insert(newEntity);
            }else {
                //代表编辑实体，其中包括实际规则的新增、删除和编辑
                BeanUtil.copyProperties(saveDTO,ruleEntity);
                ruleEntity.setNoRepeatRule(noRepeatRuleStr);
                ruleEntity.setCheckToolRule(checkToolRuleStr);
                result = recheckingRuleModel.save(ruleEntity);
            }
            if (Objects.equals(result,BasicConstant.ONE)){
                //全局更新其他模板的常用查重按钮和名称字段，电话字段的全局
                syncGlobalToRecheckRule(saveDTO);
                //重复规则保存时同步表单解释新建不允许重复的 explains
                syncRecheckRuleToExplains(saveDTO);
            }
        }catch (XbbException e){
            log.error("com.xbongbong.saas.service.impl.RecheckingRuleServiceImpl.save,重复规则保存失败",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        try {
            saveLog(oldNormalEnable,oldUpdateTimeLong,saveDTO);
        }catch (Exception e){
            log.error("com.xbongbong.saas.service.impl.RecheckingRuleServiceImpl.save,重复规则日志保存失败",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return result;
    }

    /**
     * @description 重复规则保存日志
     * @param oldNormalEnable 更新之前未启用的
     * @param oldUpdateTimeLong 老的更新时间
     * @param saveDTO  新的内容
     * @author yanglei
     * @date 2022/12/8 16:50
     */
    public void saveLog(Integer oldNormalEnable,Long oldUpdateTimeLong,RecheckingRuleSaveDTO saveDTO) throws XbbException {
        String corpid = saveDTO.getCorpid();
        String userId = saveDTO.getUserId();
        Long formId = saveDTO.getFormId();
        String loginUserName = saveDTO.getLoginUserName();
        Integer businessType = saveDTO.getBusinessType();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        OperateModuleTypeEnum operateModuleTypeEnum = null;
        PaasFormEntityExt paasForm = paasFormModel.getByKey(formId,corpid);
        PaasFormExplainEntity explainEntity = paasFormExplainModel.getByFormId(paasForm.getId(), corpid);
        if (Objects.isNull(explainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(explainEntity.getExplains(), FieldAttrEntity.class);
        Map<String, String> attrNameMap = explainList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, FieldAttrEntity::getAttrName));
        //封装attr -> attrName
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) && Objects.nonNull(fieldAttrEntity.getSubForm())){
                List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                if (CollectionsUtil.isNotEmpty(subExplainList)){
                    subExplainList.forEach(item -> attrNameMap.put(item.getParentAttr() + "." + item.getAttr() ,item.getAttrName()));
                }
            }else {
                attrNameMap.put(fieldAttrEntity.getAttr(),fieldAttrEntity.getAttrName());
            }
        }
        switch (xbbRefTypeEnum){
            case CUSTOMER_MANAGEMENT:
                operateModuleTypeEnum = OperateModuleTypeEnum.CUSTOMER;
                break;
            case CONTACT:
                operateModuleTypeEnum = OperateModuleTypeEnum.CONTACT;
                break;
            case CLUE:
                operateModuleTypeEnum = OperateModuleTypeEnum.CLUE;
                break;
            case SALES_OPPORTUNITY:
                operateModuleTypeEnum = OperateModuleTypeEnum.OPPORTUNITY;
                break;
            default:
                break;
        }
        //常用查重规则启用未启用
        Integer newNormalEnable = saveDTO.getNormalEnable();
        String memo;
        if (!Objects.equals(oldNormalEnable,newNormalEnable)){
            OperateTypeEnum operateTypeEnum = Objects.equals(newNormalEnable,BasicConstant.ONE) ? OperateTypeEnum.ENABLE : OperateTypeEnum.CLOSE;
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_NORMAL_RECHECK), loginUserName,operateTypeEnum.getName(),paasForm.getName());
            mongoLogHelp.buildLog(corpid, userId, loginUserName, operateModuleTypeEnum,operateTypeEnum,
                    null, operateModuleTypeEnum.getName(), memo, saveDTO.getHttpHeader());
        }
        //高级查重日志处理
        List<DetailLogPojo> detailArr = new ArrayList<>();
        Map<String, String> oldRuleMemoMap = saveDTO.getOldRuleMemoMap();
        Map<String, String> newRuleMemoMap = saveDTO.getNewRuleMemoMap();
        memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_SENIOR_RECHECK), loginUserName,paasForm.getName());
        //编辑
        List<String> editDetailAttrList = new ArrayList<>();
        if (Objects.nonNull(newRuleMemoMap) && Objects.nonNull(oldRuleMemoMap) ){
            for(Map.Entry<String,String> oldEntry : oldRuleMemoMap.entrySet()){
                for(Map.Entry<String,String> newEntry : newRuleMemoMap.entrySet()){
                    if(Objects.equals(oldEntry.getKey(),newEntry.getKey())){
                        detailArr.add(new DetailLogPojo(attrNameMap.getOrDefault(oldEntry.getKey(),""), oldEntry.getValue(),newEntry.getValue()));
                        editDetailAttrList.add(oldEntry.getKey());
                        break;
                    }
                }
            }
        }
        //新增
        if (Objects.nonNull(oldRuleMemoMap)){
            for(Map.Entry<String,String> oldEntry : oldRuleMemoMap.entrySet()){
                if (!editDetailAttrList.contains(oldEntry.getKey())){
                    detailArr.add(new DetailLogPojo(attrNameMap.getOrDefault(oldEntry.getKey(),""), oldEntry.getValue(),newRuleMemoMap.getOrDefault(oldEntry.getKey(),"")));
                }
            }
        }
        //删除
        if (Objects.nonNull(newRuleMemoMap)){
            for(Map.Entry<String,String> newEntry : newRuleMemoMap.entrySet()){
                if (!editDetailAttrList.contains(newEntry.getKey())){
                    detailArr.add(new DetailLogPojo(attrNameMap.getOrDefault(newEntry.getKey(),""), oldRuleMemoMap.getOrDefault(newEntry.getKey(),""),newEntry.getValue()));
                }
            }
        }
        //更新时间
        SimpleDateFormat SDF = new SimpleDateFormat(DateTimeEnum.DATETIME.getType());
        String oldUpdateTime = DateTimeUtil.getStringEpochSecond(oldUpdateTimeLong, SDF);
        String newUpdateTime = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getInt(), SDF);
        detailArr.add(new DetailLogPojo(I18nMessageUtil.getMessage(CommonConstant.UPDATE_TIME), oldUpdateTime,newUpdateTime));
        mongoLogHelp.buildLog4DetailArr(detailArr, corpid, userId, loginUserName, operateModuleTypeEnum,OperateTypeEnum.EDIT,
                null, operateModuleTypeEnum.getName(), memo, saveDTO.getHttpHeader());

    }

    /**
     * @description   高级版套餐保存的重复规则的前置校验：一个字段只能在一个规则中出现一次
     * @author yanglei
     * @date 2022/11/11 15:27
     * @param businessType 业务类型
     * @param rulePojos 规则
     */
    public void verifyAttrRepeat(Integer businessType, List<RecheckFormRulePojo> rulePojos) throws XbbException {
        if (CollectionsUtil.isEmpty(rulePojos)){
            return;
        }
        List<String> attrList = new ArrayList<>();
        for (RecheckFormRulePojo rulePojo : rulePojos){
            RecheckAttrRulePojo attrRulePojo = recheckingRuleHelp.getRecheckAttrRuleByBusinessType(businessType, rulePojo);
            if(attrRulePojo == null){
                continue;
            }
            attrList.add(attrRulePojo.getAttr());
        }
        //如果去重之后全部的attr出现次数与规则数不相等，证明有某个字段出现了多次
        if (!Objects.equals(rulePojos.size(),Integer.parseInt(String.valueOf(attrList.stream().distinct().count())))){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.RULES_MUST_CORRESPOND);
        }
    }
    
    /**
     * @description 表单解释和重复规则之间的通不过，下面方法有两个动作
     *              1、重复规则保存时同步表单解释新建不允许重复的 explains
     *              2、保存表单解释时，将勾选新建不允许重复的字段，封装成规则到tb_rechecking_rule
     * @author yanglei
     * @date 2022/11/14 9:01
     * @param saveDTO 重复规则
     */
    public void syncRecheckRuleToExplains(RecheckingRuleSaveDTO saveDTO) throws XbbException{
        List<RecheckFormRulePojo> noRepeatRuleList = saveDTO.getNoRepeatRule();
        Integer businessType = saveDTO.getBusinessType();
        Long formId = saveDTO.getFormId();
        String corpid = saveDTO.getCorpid();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        //2、同步到表单解释
        String nameRepeatConfig = FormConfigEnum.CUSTOMER_NAME_REPEAT_TYPE.getConfig();
        String phoneRepeatConfig = FormConfigEnum.CUSTOMER_PHONE_REPEAT_TYPE.getConfig();
        if (Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())) {
            nameRepeatConfig = FormConfigEnum.CLUE_NAME_REPEAT_TYPE.getConfig();
            phoneRepeatConfig = FormConfigEnum.CLUE_PHONE_REPEAT_TYPE.getConfig();
        }else if (Objects.equals(businessType,XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())){
            nameRepeatConfig = FormConfigEnum.OPPORTUNITY_NAME_REPEAT_TYPE.getConfig();
            phoneRepeatConfig = "";
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        packageExplainsFromNoRepeatRule(nameRepeatConfig,phoneRepeatConfig,corpid,paasFormExplainEntity.getMenuId(),
                businessType,explainList,recheckingRuleHelp.getAttrToIsAllMap(noRepeatRuleList,businessType),formId,false);
        paasFormExplainEntity.setExplains(JSON.toJSONString(explainList));
        paasFormExplainModel.update(paasFormExplainEntity);
    }

    /**
     * @description 全局更新其他模板的常用查重按钮和名称电话的全局匹配
     * @author yanglei
     * @date 2022/12/16 10:37
     * @param saveDTO 前端传参
     */
    private void syncGlobalToRecheckRule(RecheckingRuleSaveDTO saveDTO) throws XbbException {
        String corpid = saveDTO.getCorpid();
        Integer businessType = saveDTO.getBusinessType();
        Integer normalEnable = saveDTO.getNormalEnable();
        Long formId = saveDTO.getFormId();
        //当前业务所有启用的模板
        List<Long> enableFormIdList = paasFormModel.getFormIdList4Distributor( businessType,corpid, DistributorMarkEnum.OTHER.getCode());
        //当前业务保存过重复规则模板id
        List<Long> updateFormIdList = recheckingRuleModel.getFormIdListByBusinessType(businessType, corpid);
        //剩余其他模板需要新增的规则
        enableFormIdList.removeIf(updateFormIdList::contains);
        List<RecheckingRuleEntity> insertList = new ArrayList<>();
        //1、常用查重按钮全局更新
        for (Long otherFormId : enableFormIdList) {
            RecheckingRuleEntity recheckingRuleEntity = recheckingAddRuleHelp.initDefaultRecheckRuleEntity(businessType);
            recheckingRuleEntity.setCorpid(corpid);
            recheckingRuleEntity.setFormId(otherFormId);
            recheckingRuleEntity.setNormalEnable(normalEnable);
            insertList.add(recheckingRuleEntity);
        }
        if (CollectionsUtil.isNotEmpty(insertList)){
            recheckingRuleModel.insertBatch(insertList);
        }
        // 2、新建不允许重复规则中名称和电话字段全局更新
        Map<String, Integer> newAttrToIsAllMap = recheckingRuleHelp.getAttrToIsAllMap(saveDTO.getNoRepeatRule(), businessType);

        List<RecheckingRuleEntity> updateRuleList = recheckingRuleModel.getByBusinessType(businessType, corpid);
        updateRuleList.removeIf(item -> Objects.equals(item.getFormId(),formId));

        List<RecheckingRuleEntity> finalUpdateRuleList = new ArrayList<>();

        for (RecheckingRuleEntity updateEntity : updateRuleList) {
            boolean isUpdateName = false;
            boolean isUpdatePhone = false;
            boolean isUpdateNormal = false;
            if (Objects.nonNull(newAttrToIsAllMap)){
                isUpdateName = generateUpdateRecheckRule(StringConstant.NAME,newAttrToIsAllMap,updateEntity,businessType);
            }
            if (Objects.nonNull(newAttrToIsAllMap) && !Objects.equals(businessType,XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())){
                isUpdatePhone = generateUpdateRecheckRule(StringConstant.PHONE,newAttrToIsAllMap,updateEntity,businessType);
            }
            if (!Objects.equals(updateEntity.getNormalEnable(),normalEnable)){
                updateEntity.setNormalEnable(normalEnable);
                isUpdateNormal = true;
            }
            if (isUpdateName || isUpdatePhone || isUpdateNormal){
                finalUpdateRuleList.add(updateEntity);
            }
        }
        if (CollectionsUtil.isNotEmpty(finalUpdateRuleList)){
            recheckingRuleModel.updateBatch(finalUpdateRuleList,corpid);
        }
    }


    private boolean generateUpdateRecheckRule(String nameOrPhoneAttr,Map<String, Integer> newAttrToIsAllMap,RecheckingRuleEntity updateEntity,Integer businessType){
        Map<String, Integer> oldAttrToIsAllMap = recheckingRuleHelp.getAttrToIsAllMap(JSONArray.parseArray(updateEntity.getNoRepeatRule(), RecheckFormRulePojo.class), businessType);
        List<RecheckFormRulePojo> updateFormPojo = JSONArray.parseArray(updateEntity.getNoRepeatRule(), RecheckFormRulePojo.class);
        //证明新配置都配了名称或者电话字段的规则
        Integer newIsAll = newAttrToIsAllMap.get(nameOrPhoneAttr);
        if (Objects.equals(newIsAll,BasicConstant.ONE)){
            //1)、如果名称字段新的配置是全局，那就得同步到其他模板的规则 ,如果老的配置 配了名称字段 更新操作
            if (Objects.nonNull(oldAttrToIsAllMap.get(nameOrPhoneAttr))){
                for (RecheckFormRulePojo recheckFormRulePojo : updateFormPojo) {
                    RecheckAttrRulePojo attrRulePojo = recheckingRuleHelp.getRecheckAttrRuleByBusinessType(businessType, recheckFormRulePojo);
                    if (Objects.nonNull(attrRulePojo) && Objects.equals(attrRulePojo.getAttr(),nameOrPhoneAttr)){
                        attrRulePojo.setLinkFormId(0L);
                        attrRulePojo.setIsAll(newIsAll);
                        recheckingAddRuleHelp.setRecheckFormRulePojo(recheckFormRulePojo,businessType,Arrays.asList(attrRulePojo));
                        break;
                    }
                }
            }else {
                //新增
                RecheckFormRulePojo nameFormRulePojo = new RecheckFormRulePojo();
                List<RecheckAttrRulePojo> noRepeateAttrList = new ArrayList<>();
                noRepeateAttrList.add(new RecheckAttrRulePojo(newIsAll,nameOrPhoneAttr,nameOrPhoneAttr,0L,RecheckMatchWayEnum.EXACT_MATCH.getCode(), businessType));
                recheckingAddRuleHelp.setRecheckFormRulePojo(nameFormRulePojo,businessType,noRepeateAttrList);
                updateFormPojo.add(nameFormRulePojo);
            }
            updateEntity.setNoRepeatRule(JSON.toJSONString(updateFormPojo));
            return true;
        }else if (Objects.equals(newIsAll,BasicConstant.ZERO)) {
            // 2)、如果新的配置切成了仅模板内，需要看老的配置是否是全局，如果是全局则更新所有模板
            if (Objects.equals(oldAttrToIsAllMap.get(nameOrPhoneAttr),BasicConstant.ONE)){
                for (RecheckFormRulePojo recheckFormRulePojo : updateFormPojo) {
                    RecheckAttrRulePojo attrRulePojo = recheckingRuleHelp.getRecheckAttrRuleByBusinessType(businessType, recheckFormRulePojo);
                    if (Objects.nonNull(attrRulePojo) && Objects.equals(attrRulePojo.getAttr(),nameOrPhoneAttr)){
                        attrRulePojo.setLinkFormId(updateEntity.getFormId());
                        attrRulePojo.setIsAll(newIsAll);
                        break;
                    }
                }
                updateEntity.setNoRepeatRule(JSON.toJSONString(updateFormPojo));
                return true;
            }
        }else if (Objects.isNull(newIsAll)){
            // 3) 从全局判重 ->  删除了名称和电话规则,同步到其他模板
            if (Objects.equals(oldAttrToIsAllMap.get(nameOrPhoneAttr),BasicConstant.ONE)){
                updateFormPojo.removeIf(item -> Objects.equals(nameOrPhoneAttr,recheckingRuleHelp.getRecheckAttrRuleByBusinessType(businessType, item).getAttr()));
                updateEntity.setNoRepeatRule(JSON.toJSONString(updateFormPojo));
                return true;
            }
        }
        return false;
    }

    @Override
    public void syncExplainsToRecheckRule(String corpid,List<FieldAttrEntity> explainList,Long formId,Integer businessType) throws XbbException {
        RecheckingRuleEntity entity = recheckingRuleModel.getRuleListByFormId(corpid, formId, businessType);
        if (Objects.isNull(entity)){
            log.error("保存表单解释时，重复规则同步失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        List<RecheckFormRulePojo> noRepeatRule = new ArrayList<>();
        try{
            packageNoRepeatRuleFromExplains(businessType,explainList,noRepeatRule,formId,false);
            entity.setNoRepeatRule(JSON.toJSONString(noRepeatRule));
            Integer save = recheckingRuleModel.save(entity);
            if (Objects.equals(save,BasicConstant.ONE)){
                //解释中名称和电话修改了匹配范围，规则表也要同步，套娃，服了！
                RecheckingRuleEntity afterSaveEntity = recheckingRuleModel.getRuleListByFormId(corpid, formId, businessType);
                RecheckingRuleSaveDTO saveDTO = new RecheckingRuleSaveDTO();
                saveDTO.setNoRepeatRule(noRepeatRule);
                saveDTO.setFormId(formId);
                saveDTO.setCorpid(corpid);
                saveDTO.setBusinessType(businessType);
                saveDTO.setNormalEnable(afterSaveEntity.getNormalEnable());
                syncGlobalToRecheckRule(saveDTO);
            }
        }catch (XbbException e){
            log.error("保存表单解释时，重复规则同步失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * @description 封装表单解释中勾选的新建不允许重复规则
     * @author yanglei
     * @date 2022/11/24 15:42
     * @param businessType 业务类型
     * @param explainList 表单解释
     * @param noRepeatRule 规则
     * @param formId 表单id
     * @param isSubForm 是否子表单
     */
    private void packageNoRepeatRuleFromExplains(Integer businessType,List<FieldAttrEntity> explainList,List<RecheckFormRulePojo> noRepeatRule,Long formId,Boolean isSubForm){
        if (CollectionsUtil.isNotEmpty(explainList)){
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (Objects.nonNull(fieldAttrEntity)){
                    //过滤掉隐藏字段和未启用字段
                    if(Objects.equals(fieldAttrEntity.getEditHide(), BasicConstant.ONE) || !Objects.equals(fieldAttrEntity.getIsOpen(), BasicConstant.ONE)){
                        continue;
                    }
                    if (FieldTypeEnum.isSubFormType(fieldAttrEntity.getFieldType())){
                        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                        //判断内层的表单是否处于启用状态
                        if (Objects.nonNull(subForm) && CollectionsUtil.isNotEmpty(subForm.getItems())){
                            List<FieldAttrEntity> items = (List<FieldAttrEntity>) subForm.getItems();
                            packageNoRepeatRuleFromExplains(businessType,items,noRepeatRule,formId,true);
                            continue;
                        }
                    }
                    String finalAttr = isSubForm ? fieldAttrEntity.getParentAttr() + "." + fieldAttrEntity.getAttr() : fieldAttrEntity.getAttr();
                    //证明开启了新建不允许重复
                    if (Objects.equals(fieldAttrEntity.getNoRepeat(),BasicConstant.ONE)){
                        //默认全局判重
                        Long linkFormId = 0L;
                        Integer isAll = 1;
                        if(Objects.equals(finalAttr,StringConstant.NAME)){
                            //客户名称，线索名称 机会名称 全局判重还是仅模板内
                            if (!Objects.equals(fieldAttrEntity.getCustomerNameRepeatType(),RepeatTypeEnum.REPEAT_ALL.getType())){
                                linkFormId = formId;
                                isAll = BasicConstant.ZERO;
                            }
                        } else if(Objects.equals(finalAttr,StringConstant.PHONE) && (Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),businessType)
                                || Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode()))){
                            //客户电话 线索 电话字段 全局判重还是仅模板内
                            if (!Objects.equals(fieldAttrEntity.getCustomerPhoneRepeatType(),RepeatTypeEnum.REPEAT_ALL.getType())){
                                linkFormId = formId;
                                isAll = BasicConstant.ZERO;
                            }
                        }else if(Objects.equals(fieldAttrEntity.getIsRedundant(),BasicConstant.ONE)){
                            //自定义单行文本字段 全局判重还是仅模板内
                            if (!Objects.equals(fieldAttrEntity.getCustomRepeatType(),RepeatTypeEnum.REPEAT_ALL.getType())){
                                linkFormId = formId;
                                isAll = BasicConstant.ZERO;
                            }
                        } else {
                            //其他系统字段，非名称和电话
                            linkFormId = formId;
                            isAll = BasicConstant.ZERO;
                        }
                        RecheckFormRulePojo recheckFormRulePojo = new RecheckFormRulePojo();
                        List<RecheckAttrRulePojo> attrRulePojoList = new ArrayList<>();
                        RecheckAttrRulePojo recheckAttrRulePojo = new RecheckAttrRulePojo(0,finalAttr, finalAttr, linkFormId, RecheckMatchWayEnum.EXACT_MATCH.getCode(), businessType);
                        recheckAttrRulePojo.setIsAll(isAll);
                        attrRulePojoList.add(recheckAttrRulePojo);
                        recheckingAddRuleHelp.setRecheckFormRulePojo(recheckFormRulePojo,businessType,attrRulePojoList);
                        noRepeatRule.add(recheckFormRulePojo);
                    }
                }
            }
        }
    }


    private void packageExplainsFromNoRepeatRule(String nameRepeatConfig,String phoneRepeatConfig,String corpid,Long menuId,Integer businessType,List<FieldAttrEntity> explainList,Map<String,Integer> attrIsAllMap,Long formId,Boolean isSubForm) throws XbbException {
        if (CollectionsUtil.isNotEmpty(explainList)){
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (Objects.nonNull(fieldAttrEntity)){
                    String finalAttr = isSubForm ? fieldAttrEntity.getParentAttr() + "." + fieldAttrEntity.getAttr() : fieldAttrEntity.getAttr();
                    Integer isAll = attrIsAllMap.get(finalAttr);
                    //1、其他字段,只要是isAll为空，都要修改noRepeat
                    if (Objects.nonNull(isAll)){
                        fieldAttrEntity.setNoRepeat(BasicConstant.ONE);
                    }else {
                        fieldAttrEntity.setNoRepeat(BasicConstant.ZERO);
                    }
                    //2、客户、线索、客户名称，电话字段，全部模板 需要同步 -> formConfig ； 机会：名称 需要同步 -> formConfig
                    if (!Objects.equals(businessType,XbbRefTypeEnum.CONTACT.getCode())){
                        if (Objects.equals(finalAttr, StringConstant.NAME)) {
                            FormConfigEntity formConfigEntity = formConfigModel.getEntityByFormId(corpid, formId, nameRepeatConfig);
                            recheckingRuleHelp.updateNamePhoneToFormConfig(isAll,formConfigEntity,nameRepeatConfig,corpid,menuId,businessType);
                            continue;
                        }
                        if (Objects.equals(finalAttr, StringConstant.PHONE) && !Objects.equals(businessType,XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())) {
                            FormConfigEntity formConfigEntity = formConfigModel.getEntityByFormId(corpid, formId, phoneRepeatConfig);
                            recheckingRuleHelp.updateNamePhoneToFormConfig(isAll,formConfigEntity,phoneRepeatConfig,corpid,menuId,businessType);
                            continue;
                        }
                    }
                    //3、自定义和系统单行文本字段解释处理
                    if (Objects.equals(fieldAttrEntity.getFieldType(),FieldTypeEnum.TEXT.getType()) || Objects.equals(fieldAttrEntity.getFieldType(),FieldTypeEnum.SERIALNO.getType())){
                        //自定义单行文本
                        if(Objects.equals(fieldAttrEntity.getIsRedundant(),BasicConstant.ONE)) {
                            if (Objects.equals(isAll,BasicConstant.ONE)){
                                fieldAttrEntity.setCustomRepeatType(RepeatTypeEnum.REPEAT_ALL.getType());
                                continue;
                            }else if(Objects.equals(isAll,BasicConstant.ZERO)){
                                fieldAttrEntity.setCustomRepeatType(RepeatTypeEnum.REPEAT_SINGLE.getType());
                                continue;
                            } else {
                                fieldAttrEntity.setCustomRepeatType(RepeatTypeEnum.REPEAT_CANCEL.getType());
                                continue;
                            }
                        }
                    }
                    SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                    //4、除电话之外的子表单处理
                    if(FieldTypeEnum.isSubFormType(fieldAttrEntity.getFieldType()) && Objects.nonNull(subForm)){
                        List<FieldAttrEntity> items = (List<FieldAttrEntity>) subForm.getItems();
                        if (CollectionsUtil.isNotEmpty(items)){
                            packageExplainsFromNoRepeatRule(nameRepeatConfig,phoneRepeatConfig,corpid,menuId,businessType,items,attrIsAllMap,formId,true);
                        }
                    }
                }
            }
        }
    }

    @Override
    public RecheckingRuleListVO getList(RecheckingRuleGetDTO ruleGetDTO) throws XbbException {
        RecheckingRuleListVO recheckingRuleListVO = new RecheckingRuleListVO();
        try {
            //获取到当前模板的重复规则
            Integer businessType = ruleGetDTO.getBusinessType();
            RecheckingRuleEntity entity = recheckingRuleModel.getRuleListByFormId(ruleGetDTO.getCorpid(), ruleGetDTO.getFormId(),businessType);
            formatRecheckingRuleListVO(recheckingRuleListVO,entity,businessType);
        }catch (XbbException e){
            log.error("获取重复规则列表出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return recheckingRuleListVO;
    }
    /**
     * @description 格式vo,返回前端使用
     * @author yanglei
     * @date 2022/11/16 14:58
     * @param recheckingRuleListVO
     * @param entity
     * @param businessType
     */
    public void formatRecheckingRuleListVO(RecheckingRuleListVO recheckingRuleListVO,RecheckingRuleEntity entity,Integer businessType){
        List<RecheckFormRulePojo> noRepeatRule = JSONArray.parseArray(entity.getNoRepeatRule(), RecheckFormRulePojo.class);
        List<RecheckFormRulePojo> checkToolRule = JSONArray.parseArray(entity.getCheckToolRule(), RecheckFormRulePojo.class);
        formatRecheckFormRulePojo(noRepeatRule,businessType);
        formatRecheckFormRulePojo(checkToolRule,businessType);
        recheckingRuleListVO.setId(entity.getId());
        recheckingRuleListVO.setNoRepeatRule(noRepeatRule);
        recheckingRuleListVO.setCheckToolRule(checkToolRule);
        recheckingRuleListVO.setNormalEnable(entity.getNormalEnable());
    }
    /**
     * @description 查线索、查客户、查联系人、查机会的规则一旦为空，塞个空数组
     * @author yanglei
     * @date 2022/11/16 15:08
     * @param formRulePojos
     * @param businessType
     */
    public void formatRecheckFormRulePojo(List<RecheckFormRulePojo> formRulePojos,Integer businessType){
        for (RecheckFormRulePojo formRulePojo : formRulePojos) {
            if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
                //线索有联合查重所以这边特殊处理
                List<Integer> clueCheckBusinessList = Arrays.asList(XbbRefTypeEnum.CONTACT.getCode(), XbbRefTypeEnum.CLUE.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                for (Integer type : clueCheckBusinessList) {
                    RecheckAttrRulePojo attrRulePojo = recheckingRuleHelp.getRecheckAttrRuleByBusinessType(type, formRulePojo);
                    if (Objects.isNull(attrRulePojo)){
                        //如果规则为空，塞个空的给前端用
                        recheckingAddRuleHelp.setRecheckFormRulePojo(formRulePojo,type,new ArrayList<>());
                    }
                }
            }else {
                RecheckAttrRulePojo attrRulePojo = recheckingRuleHelp.getRecheckAttrRuleByBusinessType(businessType, formRulePojo);
                if (Objects.isNull(attrRulePojo)){
                    //如果规则为空，塞个空的给前端用
                    recheckingAddRuleHelp.setRecheckFormRulePojo(formRulePojo,businessType,new ArrayList<>());
                }
            }
        }
    }

    @Override
    public RecheckingFieldListVO getRecheckAttrAndFormList(RecheckingRuleGetDTO recheckingRuleGetDTO) throws XbbException {
        Long formId = recheckingRuleGetDTO.getFormId();
        String corpid = recheckingRuleGetDTO.getCorpid();
        Integer businessType = recheckingRuleGetDTO.getBusinessType();
        RecheckingFieldListVO recheckingFieldListVO = new RecheckingFieldListVO();
        try{
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            //当前模板的查重可选字段
            List<RecheckJointLinkAttrPojo> currentAttrList = getChooseAttr(corpid,formId);
            //当前业务的所有模板列表
            List<ClueRecheckFormPojo> currentFormList = getTemplateList(corpid,businessType);
            switch (xbbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    recheckingFieldListVO.setCustomerFormList(currentFormList);
                    recheckingFieldListVO.setCustomerAttrList(currentAttrList);
                    break;
                case CLUE:
                    RecheckingRuleGetDTO ruleGetDTO = new RecheckingRuleGetDTO();
                    ruleGetDTO.setCorpid(corpid);
                    ruleGetDTO.setBusinessType(XbbRefTypeEnum.CONTACT.getCode());
                    ruleGetDTO.setOperateFlag(BasicConstant.ONE);
                    recheckingFieldListVO.setClueAttrList(currentAttrList);
                    recheckingFieldListVO.setClueFormList(currentFormList);
                    //获取联系人的表单模板可选字段
                    recheckingFieldListVO.setContactAttrList(getRecheckAttrByForm(ruleGetDTO).getFormAttrList());
                    //获取联系人的表单单模板
                    recheckingFieldListVO.setContactFormList(getTemplateList(corpid,XbbRefTypeEnum.CONTACT.getCode()));
                    //获取客户所有表单模板
                    recheckingFieldListVO.setCustomerFormList(getTemplateList(corpid,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()));
                    //获取客户所有的查重可选字段
                    ruleGetDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                    recheckingFieldListVO.setCustomerAttrList(getRecheckAttrByForm(ruleGetDTO).getFormAttrList());
                    break;
                case CONTACT:
                    recheckingFieldListVO.setContactFormList(currentFormList);
                    recheckingFieldListVO.setContactAttrList(currentAttrList);
                    break;
                case SALES_OPPORTUNITY:
                    recheckingFieldListVO.setOpportunityFormList(currentFormList);
                    recheckingFieldListVO.setOpportunityAttrList(currentAttrList);
                    break;
                default:
                    break;
            }
        }catch (Exception e){
            log.error("getRecheckAttrAndFormList,获取查重可选字段出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return recheckingFieldListVO;
    }

    @Override
    public RecheckingAttrListVO getRecheckAttrByForm(RecheckingRuleGetDTO recheckingRuleGetDTO) throws XbbException {
        Long singleFormId = recheckingRuleGetDTO.getFormId();
        Integer businessType = recheckingRuleGetDTO.getBusinessType();
        String corpid = recheckingRuleGetDTO.getCorpid();
        RecheckingAttrListVO attrListVO = new RecheckingAttrListVO();
        try{
            List<FieldAttrEntity> explainsList = new ArrayList<>();
            if (Objects.nonNull(singleFormId)){
                //单模板解释
                explainsList = getSingleFormChooseAttrList(corpid,singleFormId);
            }else {
                //多模板解释
                explainsList = getAllFormExplainsList(corpid, businessType,recheckingRuleGetDTO.getOperateFlag());
            }
            attrListVO.setFormAttrList(resultDeal(explainsList));
            return attrListVO;
        }catch (Exception e){
            log.error("通过模板获取可选字段报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
        }
    }


    /**
     * @description 获取指定业务的模板列表
     * @author yanglei
     * @date 2022/11/10 17:29
     * @param corpid
     * @param businessType
     * @return List<ClueRecheckFormPojo>
     */
    public List<ClueRecheckFormPojo> getTemplateList(String corpid,Integer businessType) throws XbbException{
        List<ClueRecheckFormPojo> clueRecheckFormPojoList = new ArrayList<>();
        try {
            List<PaasFormEntityExt> enableFormList = paasFormModel.getFormListDistributor(corpid, businessType, DistributorMarkEnum.OTHER.getCode());
            if (CollectionsUtil.isEmpty(enableFormList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
            }
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            if (XbbRefTypeEnum.checkMutiFormRecheckBusinessType(businessType)){
                ClueRecheckFormPojo clueRecheckFormPojoAll = new ClueRecheckFormPojo();
                switch(xbbRefTypeEnum){
                    case CUSTOMER_MANAGEMENT:
                        clueRecheckFormPojoAll.setFormName(XbbRefTypeEnum.CUSTOMER.getName());
                        break;
                    case SALES_OPPORTUNITY:
                        clueRecheckFormPojoAll.setFormName(XbbRefTypeEnum.ALL_OPPORTUNITY.getName());
                        break;
                    case CLUE:
                        clueRecheckFormPojoAll.setFormName(XbbRefTypeEnum.ALL_CLUE.getName());
                        break;
                    default:
                        break;
                }
                //多模板的表单需要添加一个全部模板
                clueRecheckFormPojoAll.setFormId(0L);
                clueRecheckFormPojoAll.setForm("all");
                clueRecheckFormPojoAll.setIsAll(BasicConstant.ONE);
                clueRecheckFormPojoList.add(clueRecheckFormPojoAll);
            }
            for (PaasFormEntityExt paasFormEntityExt : enableFormList){
                ClueRecheckFormPojo clueRecheckFormPojo = new ClueRecheckFormPojo();
                clueRecheckFormPojo.setFormId(paasFormEntityExt.getId());
                clueRecheckFormPojo.setFormName(paasFormEntityExt.getName());
                clueRecheckFormPojo.setBusinessType(paasFormEntityExt.getBusinessType());
                clueRecheckFormPojoList.add(clueRecheckFormPojo);
            }
        } catch (XbbException e) {
            log.error("获取模板列表出错出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return clueRecheckFormPojoList;
    }

    /**
    * @description 获取线索、联系人、客户、机会的查重可选字段
    * @author yanglei
    * @date 2022/11/10 11:11
    * @param corpid 公司id
    * @param formId 表单id
    * @return List<RecheckJointLinkAttrPojo>
    */
    public List<RecheckJointLinkAttrPojo> getChooseAttr(String corpid,Long formId) throws XbbException {
        try{
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            //线索联合查重只支持单行文本类型字段（包含子表单中的单行文本），流水号，单行文本并且没有开启不允许重复值才移除，将隐藏字段去除，回收站或未启用字段移除
            explainList.removeIf(item -> !getRecheckingAttrType().contains(item.getFieldType())
                    || Objects.equals(BasicConstant.ONE, item.getEditHide())
                    || Objects.equals(BasicConstant.ZERO, item.getIsOpen())
                    || Objects.equals(BasicConstant.TWO, item.getIsOpen()));
            explainList.forEach(item -> item.setFormId(formId));
            return resultDeal(explainList);
        }catch (Exception e){
            log.error("获取查重可选字段的你出错出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    /**
     * @description 获取当前业务所有模板的解释集合
     * @author yanglei
     * @date 2022/11/10 16:27
     * @param corpid 公司id
     * @param businessType 业务类型
     * @param operateFlag 操作入口 1、代表第一次进来 0 代表选择模板的时候
     * @return Map<FieldAttrEntity>
     */
    public List<FieldAttrEntity> getAllFormExplainsList(String corpid,Integer businessType,Integer operateFlag) throws XbbException {
        List<FieldAttrEntity> allFieldAttrEntityList = new ArrayList<>();
        //获取当前业务所有启用的模板
        List<PaasFormEntityExt> enableFormList = paasFormModel.getFormListDistributor(corpid, businessType, DistributorMarkEnum.OTHER.getCode());
        List<Long> enableFormId = enableFormList.stream().map(PaasFormEntityExt::getId).collect(Collectors.toList());
        //获取当前业务所有启用的模板解释
        List<PaasFormExplainEntity> explainEntityList = paasFormExplainModel.getByFormIdIn(enableFormId, corpid);
        if(CollectionsUtil.isEmpty(explainEntityList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        for (PaasFormExplainEntity paasFormExplainEntity : explainEntityList) {
            String explains = paasFormExplainEntity.getExplains();
            if(Objects.isNull(explains) || Objects.equals("[]",explains)){
                continue;
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            explainList.forEach(item -> item.setFormId(paasFormExplainEntity.getFormId()));
            allFieldAttrEntityList.addAll(explainList);
        }
        //除单行文本、子表单外类型移除,非系统字段移除,将隐藏字段去除,处于回收站或未启用移除,全部模版将外链的拓展字段移除
        allFieldAttrEntityList.removeIf(item -> !getRecheckingAttrType().contains(item.getFieldType()) ||
                (Objects.equals(BasicConstant.ONE, item.getIsRedundant()) && Objects.equals(operateFlag,BasicConstant.ZERO)) ||
                Objects.equals(BasicConstant.ONE, item.getEditHide()) ||
                Objects.equals(BasicConstant.ZERO, item.getIsOpen()) ||
                Objects.equals(BasicConstant.TWO, item.getIsOpen()) ||
                Objects.equals("extensionField", item.getSaasAttr()));
        //去重，过滤出系统字段
        List<FieldAttrEntity> distinctSystemAttrList = allFieldAttrEntityList.stream()
                .filter(item -> Objects.equals(item.getIsRedundant(), BasicConstant.ZERO))
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(FieldAttrEntity::getAttr))), ArrayList::new));
        List<FieldAttrEntity> resultList = allFieldAttrEntityList.stream()
                .filter(item -> Objects.equals(item.getIsRedundant(), BasicConstant.ONE)).collect(Collectors.toList());
        resultList.addAll(distinctSystemAttrList);
        return resultList;
    }


    /**
     * @description 获取单个模板的可选字段解释集合
     * @author yanglei
     * @date 2022/11/10 16:43
     * @param corpid
     * @param singleFormId
     * @return List<FieldAttrEntity>
     */
    public List<FieldAttrEntity> getSingleFormChooseAttrList(String corpid,Long singleFormId) throws XbbException {
        //单个模版
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(singleFormId, corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        //不符合条件字段类型移除移除,将隐藏字段去除,处于回收站或未启用移除
        explainList.removeIf(item -> !getRecheckingAttrType().contains(item.getFieldType())
                || Objects.equals(BasicConstant.ONE, item.getEditHide())
                || Objects.equals(BasicConstant.ZERO, item.getIsOpen())
                || Objects.equals(BasicConstant.TWO, item.getIsOpen()));
        explainList.forEach(item -> item.setFormId(singleFormId));
        return explainList;
    }

    /**
     * @description 可选字段结果封装处理
     * @author yanglei
     * @date 2022/11/10 14:04
     * @param explainList 表单解释
     * @return List<RecheckJointLinkAttrPojo>
     */
    private List<RecheckJointLinkAttrPojo> resultDeal(List<FieldAttrEntity> explainList){
        List<RecheckJointLinkAttrPojo> recheckJointLinkAttrPojoList = new ArrayList<>();
        for (FieldAttrEntity fieldAttrEntity : explainList){
            if(Objects.isNull(fieldAttrEntity)){
                continue;
            }
            //旗舰版才能配置自定义单行文本的关联选项
            List<CustomRecheckRulePojo> customRecheckRules = fieldAttrEntity.getCustomRecheckRules();
            //还需要考虑子表单中的单行文本
            boolean isSubForm = (Objects.equals(fieldAttrEntity.getFieldType(),FieldTypeEnum.SUB_FORM.getType())
                    ||  Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType()));
            if (isSubForm) {
                SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                if (Objects.nonNull(subForm) && CollectionsUtil.isNotEmpty(subForm.getItems())) {
                    List<? extends FieldAttrEntity> items = subForm.getItems();
                    for (FieldAttrEntity item : items) {
                        //子表单内的成员单选和单行文本支持新建不允许重复规则
                        boolean isTextOrUser = Objects.equals(item.getIsOpen(),BasicConstant.ONE) && getRecheckingAttrType().contains(item.getFieldType());
                        customRecheckRules = item.getCustomRecheckRules();
                        if (isTextOrUser) {
                            String defaultName = StringUtils.isEmpty(fieldAttrEntity.getDefaultName()) ? fieldAttrEntity.getAttrName() : fieldAttrEntity.getDefaultName();
                            recheckJointLinkAttrPojoList.add(new RecheckJointLinkAttrPojo(fieldAttrEntity.getFormId(),
                                    fieldAttrEntity.getAttr() + "." + item.getAttr(), defaultName  + "." + item.getAttrName(),
                                    item.getFieldId(),item.getFieldType(),item.getIsRedundant(),customRecheckRules));
                        }
                    }
                }
            }else{
                String defaultName = StringUtils.isEmpty(fieldAttrEntity.getDefaultName()) ? fieldAttrEntity.getAttrName() : fieldAttrEntity.getDefaultName();
                recheckJointLinkAttrPojoList.add(new RecheckJointLinkAttrPojo(fieldAttrEntity.getFormId(),
                        fieldAttrEntity.getAttr(), defaultName,fieldAttrEntity.getFieldId(),fieldAttrEntity.getFieldType(),
                        fieldAttrEntity.getIsRedundant(),customRecheckRules));
            }
        }
        return recheckJointLinkAttrPojoList;
    }
}
